// 市区范围的旋转底座

import {
	Cartesian3,
	CircleGeometry,
	EllipsoidSurfaceAppearance,
	GeometryInstance,
	Material,
	GroundPrimitive,
	PrimitiveCollection,
	Viewer,
	Color
} from 'cesium'

import {
	point as tfPoint,
	points as tfPoints,
	convex as tfConvex,
	center as tfCenter,
	distance as tfDistance
} from '@turf/turf'

class Baseplate {

	viewer : Viewer | null
	isLoad : boolean = false

	baseplatePrimitives : PrimitiveCollection | null
	rotateColor : Array<any> = [102, 184, 217, 0.6]
	fixedColor : Array<any> = [102, 184, 217, 0.2]
	diffuseColor : Array<any> = [102, 184, 217, 0.2]

	constructor(viewer : Viewer) {
		this.viewer = viewer
	}

	// 加载数据
	async load(code : string) {
		if (this.isLoad == true) return
		this.isLoad = true

		this.baseplatePrimitives = new PrimitiveCollection()
		this.viewer.scene.primitives.add(this.baseplatePrimitives)

		let result = await import(`../../../../static/gisData/Provinces.json`)
		if (result == null) {
			this.isLoad = false
			return
		}
		let features = result.features.filter((feature : any) => {
			return feature.properties.CODE == code
		})

		const lonlats = this.parseGeojson({ type: 'FeatureCollection', features })

		const points = tfPoints(lonlats)
		const convex = tfConvex(points)
		const center = tfCenter(convex)
		const distance = tfDistance(center.geometry, convex.geometry.coordinates[0][0], { units: `meters` })

		this.createFixedPlatePrimitive(this.viewer, center.geometry.coordinates, distance)
		this.createRotatePlatePrimitive(this.viewer, center.geometry.coordinates, distance)
		this.createDiffusionPrimitive(this.viewer, center.geometry.coordinates, distance)
	}

	// 将geojson解析成坐标数组
	parseGeojson(geojson : any) {
		if (geojson == null) return []
		if (geojson.type == 'FeatureCollection') {
			return parseFeatureC(geojson)
		}
		else if (geojson.type == 'Feature') {
			return parseFeacture(geojson)
		}

		function parseFeatureC(geojson : any) {
			if (geojson.type == 'FeatureCollection') {
				return geojson.features.map((item : any) => { return parseFeacture(item) })[0]
			}
			else return null
		}

		function parseFeacture(geojson : any) {
			if (geojson.type != 'Feature') return null
			if (geojson.geometry == null) return null
			const geometry = geojson.geometry
			return parseGeometry(geometry)
		}

		function parseGeometry(geometry : any) {
			if (geometry.type == 'MultiPolygon') {
				const coordinates = geometry.coordinates[0][0]
				let lonlats = []
				coordinates.forEach((item) => { lonlats.push([...item]) })
				return lonlats
			}
			else if (geometry.type == 'Polygon') {
				const coordinates = geometry.coordinates[0]
				let lonlats = []
				coordinates.forEach((item) => { lonlats.push([...item]) })
				return lonlats
			}
			else return null
		}
	}

	// 创建固定底盘
	private createFixedPlatePrimitive(viewer : Viewer, center : Array<number>, radius : number) {
		const color = this.fixedColor
		const circleGeom = new CircleGeometry({
			center: Cartesian3.fromDegrees(center[0], center[1]),
			radius: radius
		})
		const instance = new GeometryInstance({
			geometry: circleGeom
		})
		const appearance = new EllipsoidSurfaceAppearance({
			material: new Material({
				fabric: {
					uniforms: {
						time: 0,
						color: new Color(color[0] / 255, color[1] / 255, color[2] / 255, color[3])
					},
					source: `
					    uniform vec4 color;
					    float scrollH = 0.4;
						float PI = 3.1415926;
					    
					    czm_material czm_getMaterial(czm_materialInput materialInput) {
					    	czm_material material = czm_getDefaultMaterial(materialInput);
					    	vec2 st = materialInput.st;
					    	
							float dis = sqrt(pow(st.s-0.5, 2.0) + pow(st.t-0.5, 2.0));
							material.alpha = 0.0;
							if(dis>0.395 && dis<0.4) {
								material.diffuse = color.rgb;
								material.alpha = color.a;
								
								float angle = acos(dot(vec2(0.0,0.5),vec2(st.s-0.5,st.t-0.5))/(0.5 * dis));
								vec3 rotate = cross(vec3(0.0,0.5,0.0),vec3(st.s-0.5,st.t-0.5,0.0));
								if(rotate.z > 0.0) angle = 2.0 * PI - angle;
								angle += 0.7;
							
							    angle -= time;
								float diff = mod(angle, (2.0 * PI / 3.0));
								if(diff < 2.0 * PI / 3.0 / 6.0 || diff > 2.0 * PI / 3.0 / 6.0 * 5.0) {
									material.alpha = 0.05;
								}
							}
							
					    	return material;
					    }
					`
				}
			})
		})
		const primitive = new GroundPrimitive({
			geometryInstances: instance,
			appearance,
			asynchronous: true,
			releaseGeometryInstances: true,
			compressVertices: true,
			allowPicking: false
		})
		this.baseplatePrimitives.add(primitive)
		this.viewer.scene.preRender.addEventListener(this._renderFixedEvent.bind(appearance.material))
	}
	private _renderFixedEvent() {
		const intervalTime = 2 * 3.1415926 * 20;
		const newTime = Date.now() / 1000;
		const interval = newTime % intervalTime / 30;

		this.uniforms.time = interval
	}


	// 创建旋转底盘
	private createRotatePlatePrimitive(viewer : Viewer, center : Array<number>, radius : number) {
		const color = this.rotateColor
		const circleGeom = new CircleGeometry({
			center: Cartesian3.fromDegrees(center[0], center[1]),
			radius: radius * (1 / 2)
		})
		const instance = new GeometryInstance({
			geometry: circleGeom,
		})
		const appearance = new EllipsoidSurfaceAppearance({
			material: new Material({
				fabric: {
					uniforms: {
						color: new Color(color[0] / 255, color[1] / 255, color[2] / 255, color[3]),
						time: 0
					},
					source: `
					    uniform float time;
					    uniform vec4 color;
					    float scrollH = 0.4;
						float PI = 3.1415926;
					    
					    czm_material czm_getMaterial(czm_materialInput materialInput) {
					    	czm_material material = czm_getDefaultMaterial(materialInput);
					    	vec2 st = materialInput.st;
					    	
							float dis = sqrt(pow(st.s-0.5, 2.0) + pow(st.t-0.5, 2.0));
							material.alpha = 0.0;
							if(dis>0.49) {
								material.diffuse = color.rgb;
								material.alpha = color.a;
								
								float angle = acos(dot(vec2(0.0,0.5),vec2(st.s-0.5,st.t-0.5))/(0.5 * dis));
								vec3 rotate = cross(vec3(0.0,0.5,0.0),vec3(st.s-0.5,st.t-0.5,0.0));
								if(rotate.z > 0.0) angle = 2.0 * PI - angle;
								angle -= time;
								float diff = mod(angle, (2.0 * PI / 5.0));
								if(diff < 2.0 * PI / 5.0 / 6.0 || diff > 2.0 * PI / 5.0 / 6.0 * 5.0) {
									material.alpha = 0.0;
								}
							}
							
							if(dis > 0.28 + 0.05 && dis < 0.3 + 0.05) {
								material.diffuse = color.rgb;
								material.alpha = color.a;
								
								float angle = acos(dot(vec2(0.0,0.5),vec2(st.s-0.5,st.t-0.5))/(0.5 * dis));
								vec3 rotate = cross(vec3(0.0,0.5,0.0),vec3(st.s-0.5,st.t-0.5,0.0));
								if(rotate.z > 0.0) angle = 2.0 * PI - angle;
								angle += time;
								float diff = mod(angle, (2.0 * PI / 5.0));
								if(diff < 2.0 * PI / 5.0 / 6.0 || diff > 2.0 * PI / 5.0 / 6.0 * 5.0) {
									material.alpha = 0.0;
								}
							}
							
							
					    
					    	return material;
					    }
					`
				}
			})
		})
		const primitive = new GroundPrimitive({
			geometryInstances: instance,
			appearance,
			asynchronous: true,
			releaseGeometryInstances: true,
			compressVertices: true,
			allowPicking: false
		})
		this.baseplatePrimitives.add(primitive)
		viewer.scene.preRender.addEventListener(this._renderRotateEvent.bind(appearance.material))
	}

	private _renderRotateEvent() {
		const intervalTime = 2 * 3.1415926;
		const newTime = Date.now() / 1000;
		const interval = newTime % intervalTime / 5;

		this.uniforms.time = interval
	}

	// 创建放射底盘
	private createDiffusionPrimitive(viewer : Viewer, center : Array<number>, radius : number) {
		const color = this.diffuseColor
		const circleGeom = new CircleGeometry({
			center: Cartesian3.fromDegrees(center[0], center[1]),
			radius: radius * 2
		})
		const instance = new GeometryInstance({
			geometry: circleGeom
		})
		const appearance = new EllipsoidSurfaceAppearance({
			material: new Material({
				fabric: {
					uniforms: {
						time: 0,
						color: new Color(color[0] / 255, color[1] / 255, color[2] / 255, color[3])
					},
					source: `
					    uniform float time;
					    uniform vec4 color;
					    float scrollH = 0.4;
						float PI = 3.1415926;
						float width = 0.08;
					    
					    czm_material czm_getMaterial(czm_materialInput materialInput) {
					    	czm_material material = czm_getDefaultMaterial(materialInput);
					    	vec2 st = materialInput.st;
					    	
							float dis = sqrt(pow(st.s-0.5, 2.0) + pow(st.t-0.5, 2.0));
							material.diffuse = color.rgb;
							material.alpha = 0.0;
							float fardis = mod(time, 0.5);
							if(dis>fardis - width && dis<fardis && dis>0.01) {
								material.diffuse = color.rgb;
								float alpha = color.a - fardis/0.5*color.a;
								alpha = alpha - abs(fardis - dis - (width / 2.0)) / (width / 2.0) * alpha;
								material.alpha = alpha;
							}
							
					    	return material;
					    }
					`
				}
			})
		})
		const primitive = new GroundPrimitive({
			geometryInstances: instance,
			appearance,
			asynchronous: true,
			releaseGeometryInstances: true,
			compressVertices: true,
			allowPicking: false
		})
		this.baseplatePrimitives.add(primitive)
		viewer.scene.preRender.addEventListener(this._renderDiffusionEvent.bind(appearance.material))
	}

	_renderDiffusionEvent() {
		let newTime = Date.now()
		let interval = newTime % 10000 / 10000

		this.uniforms.time = interval
	}


	// 卸载数据
	unload() {
		if (this.isLoad == false) return
		this.isLoad = false
		this.viewer.scene.primitives.remove(this.baseplatePrimitives)
		//this.baseplatePrimitives.destroy()
		this.baseplatePrimitives = null
		this.viewer.scene.preRender.removeEventListener(this._renderRotateEvent)
	}
}

export default Baseplate